﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using GurLoader.Service;
using GurLoader.Util;
using GurLoader.View;

namespace GurLoader.ViewModel
{
    public class GurLoaderViewModel : INotifyPropertyChanged
    {
        private static readonly PropertyChangedEventArgs commandProgressChangeArgs =
            ObservableHelper.CreateArgs<GurLoaderViewModel>(x => x.CommandProgress);

        private IDelegatingCommandProgress commandProgress;

        public GurLoaderViewModel(Progress<IDelegatingCommandProgress> progress,
            CancellationTokenSource cancellationTokenSource, ICommandManager commandManager)
        {
            if ( progress == null )
                throw new ArgumentNullException("progress");

            if ( cancellationTokenSource == null )
                throw new ArgumentNullException("cancellationTokenSource");

            if ( commandManager == null )
                throw new ArgumentNullException("commandManager");

            ProgressContainer = progress;
            CancelTokenSource = cancellationTokenSource;
            CommandManager = commandManager;

            progress.ProgressChanged += progress_ProgressChanged;
        }

        private Progress<IDelegatingCommandProgress> ProgressContainer { get; set; }
        private CancellationTokenSource CancelTokenSource { get; set; }
        private ICommandManager CommandManager { get; set; }

        public IDelegatingCommandProgress CommandProgress
        {
            get { return commandProgress; }

            set
            {
                commandProgress = value;
                NotifyPropertyChanged(commandProgressChangeArgs);
            }
        }

        public ICommand RequestCancelCommand
        {
            get
            {
                return new DelegateCommand
                {
                    CommandAction = () =>
                    {
                        CancelTokenSource.Cancel();
                    },
                    CanExecuteFunc =
                        () =>
                            !CancelTokenSource.IsCancellationRequested && CommandProgress != null &&
                            !CommandProgress.IsTotalProgressComplete
                };
            }
        }

        public ICommand BrowserOpenItemLinkCommand
        {
            get
            {
                return new RelayCommand<ICommandProgress>
                {
                    CommandAction = (p) =>
                    {
                        object result = p.Result;
                        if (result == null && p is DelegatingCommandProgress)
                        {
                            DelegatingCommandProgress dcp = p as DelegatingCommandProgress;
                            foreach (var child in dcp.Children)
                            {
                                if (child.Result != null)
                                {
                                    result = child.Result;
                                    break;
                                }
                            }
                        }

                        string linkUrl = LinkHelper.GetLinkUrl(result);
                        if (string.IsNullOrEmpty(linkUrl))
                            return;

                        Process.Start(linkUrl);
                    },
                    CanExecuteFunc = (p) =>
                    {
                        if (p == null)
                            return false;

                        return p.IsComplete;
                    }
                };
            }
        }

        public ICommand ClipboardCopyItemLinkCommand
        {
            get
            {
                return new RelayCommand<ICommandProgress>
                {
                    CommandAction = (p) =>
                    {
                        object result = p.Result;
                        if (result == null && p is DelegatingCommandProgress)
                        {
                            DelegatingCommandProgress dcp = p as DelegatingCommandProgress;
                            foreach (var child in dcp.Children)
                            {
                                if (child.Result != null)
                                {
                                    result = child.Result;
                                    break;
                                }
                            }
                        }

                        string linkUrl = LinkHelper.GetLinkUrl(result);
                        Clipboard.SetText(linkUrl);
                    },
                    CanExecuteFunc = (p) =>
                    {
                        if (p == null)
                            return false;

                        return p.IsComplete;
                    }
                };
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void progress_ProgressChanged(object sender, IDelegatingCommandProgress e)
        {
            // may need to fire changed
            if (commandProgress == null)
                CommandProgress = e;
        }

        protected void NotifyPropertyChanged(PropertyChangedEventArgs args)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, args);
            }
        }
    }
}